package com.fingard.dsp.bank.directbank.jytpay01;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.net.ConnState;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

/**
 *  金运通单笔代付
 */
public class JYTPAY01SinglePay extends JYTPAY01Base implements ISinglePay {
	/**
	 * 单笔代付交易提交
	 * 		--  单笔代付TC1002
	 * 		--  根据商户的付款请求将资金划转到企业或个人的银行账户
	 * 		--  需要向用户银行卡的付款时使用
	 */
	public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
		RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
		RetAtsSglDetail tmpRetDetail = d_190802(p_req1908);
		
		if(tmpRetDetail.respCode.equals("-1") && StringHelper.isNullOrEmpty(tmpRetDetail.reqSeqID)){
			tmpRetDetail.reqSeqID = p_req1908.singleDetail.askNumber;
		}
		
		retAts.writeRetDetail(tmpRetDetail);
		return retAts;
	}

	@Override
	public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
		return null;
	}

	//190802对外支付
	private RetAtsSglDetail d_190802(ReqSingle p_req1908) throws Exception{
		RetAtsSglDetail retDetail = new RetAtsSglDetail();
		
		ActSetItem actItem = getBankConfig().getActSetItem(p_req1908.singleDetail.payAct, "");
		if (actItem == null) {
			retDetail.respCode = "0";
			retDetail.respInfo = "未找到账号" + p_req1908.singleDetail.payAct + "对应的商户配置信息";
			retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
			retDetail.transAmt = p_req1908.singleDetail.payAmount;
			retDetail.transState = PaymentState.FAIL_Payment;
			retDetail.payInfoCode = FailCode.E9981;
			
			return retDetail;
		}
		
		JYTPAY01Header bankHeader = new JYTPAY01Header();
		bankHeader.tran_code = "TC1002";
		bankHeader.tran_flowid = actItem.merchantId + Format.DateTime14Format.format(new Date()) + String.format("%06d", new Random().nextInt(999999));
		
		XmlTextWriter xmlWriter = new XmlTextWriter();
		writeCommonHeader(xmlWriter, bankHeader, actItem);
		
		xmlWriter.writeStartElement("body");
		xmlWriter.writeElementString("mer_viral_acct", "");// 商户平台虚拟账户
		xmlWriter.writeElementString("agrt_no", "");// 协议号
		xmlWriter.writeElementString("bank_name", p_req1908.singleDetail.recBankName);// 银行名称
		xmlWriter.writeElementString("account_no", p_req1908.singleDetail.recAct);// 银行账号
		xmlWriter.writeElementString("account_name", p_req1908.singleDetail.recName);// 银行账户名
		
		// 账户类型 00：对私 01：对公
		if (p_req1908.singleDetail.isPrivate.equals("1")) {
			xmlWriter.writeElementString("account_type", "00");
		}else {
			xmlWriter.writeElementString("account_type", "01");
		}
		
		xmlWriter.writeElementString("brach_bank_province", "");// 省
		xmlWriter.writeElementString("brach_bank_city", "");// 市
		xmlWriter.writeElementString("brach_bank_name", "");// 开户行名称
		xmlWriter.writeElementString("tran_amt", p_req1908.singleDetail.payAmount);// 交易金额
		xmlWriter.writeElementString("currency", convertCurToBank(p_req1908.singleDetail.recCur));// 交易币种
		xmlWriter.writeElementString("bsn_code", getBankConfig().getMapValueByKey("payUseMapping", "1"));// 业务类型代码
		xmlWriter.writeElementString("cert_type", "");// 证件类型
		xmlWriter.writeElementString("cert_no", "");  // 证件号
		xmlWriter.writeElementString("mobile", "");// 预留手机号
		xmlWriter.writeElementString("remark", "");// 摘要
		xmlWriter.writeElementString("reserve", "");// 预留字段
		xmlWriter.writeEndElement();
		xmlWriter.writeEndDocument();
			
		// 报文明文
		WriteBankLogLn2("金运通单笔代付交易请求报文: \n" + xmlWriter.toXmlString());
		
		// 加密报文并生成签名
		String[] postStr = encryptAndSign(xmlWriter.toXmlString(),actItem);
		
		// http请求数据
		Map<String,String> postParams = new HashMap<String,String>();
		postParams.put("merchant_id", actItem.merchantId);
		postParams.put("xml_enc", postStr[0]);// 加密报文
		postParams.put("key_enc", postStr[1]);// 加密密钥
		postParams.put("sign", postStr[2]);// 签名
		
		// 发送金运通
		String[] tmpStrRet = sendToBank("unifiedPay",postParams);
		
		// 解析金运通返回
		if(tmpStrRet[0].length() == 0) {
			// http返回数据
			WriteBankLogLn2("金运通http返回数据: " + tmpStrRet[1]);
			
			String[] respHttpStr = tmpStrRet[1].split("&");
			String hexXmlEnc = respHttpStr[1].split("=")[1].replace("\"", "");// 返回报文密文
			String hexKeyEnc = respHttpStr[2].split("=")[1].replace("\"", "");// 密钥密文
			String hexSign = respHttpStr[3].split("=")[1].replace("\"", "");// 签名
			
			// 解密验签
			String[] tmpRespStr = decryptAndVeriSign(hexXmlEnc, hexKeyEnc, hexSign,actItem);
			String respXml = tmpRespStr[0];// 返回报文
			String respSign = tmpRespStr[1];// 验签结果
			
			// 验签处理
			if (respSign.equals("1")) {
				// 返回报文
				WriteBankLogStep3(respXml);
				
				// 解析报文
				StringBuilder tmpSbMsg = new StringBuilder();
				XmlTextReader tmpBkReader = loadBankRespXmlReader(respXml, tmpSbMsg);
				
				if(tmpBkReader != null) {
					String tmpRespCode = tmpBkReader.getFirstText("/message/head/resp_code");
					String tmpRespInfo = tmpBkReader.getFirstText("/message/head/resp_desc");
					
					if (tmpRespCode.equals("S0000000")) {
						retDetail.respCode = "0";
						retDetail.respInfo = tmpRespInfo;
						retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
						retDetail.transAmt = p_req1908.singleDetail.payAmount;
						retDetail.transState = tmpRespCode + "+" + tmpBkReader.getFirstText("/message/body/tran_state");
						retDetail.payInfoCode = tmpRespCode;
					}else {
						retDetail.respCode = "-1";
						retDetail.respInfo = tmpRespInfo;
					}
				}else{
					retDetail.respCode = "-1";
					retDetail.respInfo = tmpSbMsg.toString();
				}
			} else {
				retDetail.respCode = "-1";
				retDetail.respInfo = "验证签名失败!";
			}
		}else if(tmpStrRet[0].equals(ConnState.FAIL)){
			retDetail.respCode = "0";
			retDetail.respInfo = tmpStrRet[1];
			retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
			retDetail.transAmt = p_req1908.singleDetail.payAmount;
			retDetail.transState = PaymentState.FAIL_Payment;
			retDetail.payInfoCode = tmpStrRet[0];
		}else{
			retDetail.respCode = "-1";
			retDetail.respInfo = tmpStrRet[1];
		}
		
		return retDetail;
	}

	/**
	 * 单笔代付交易状态查询
	 * 		--  单笔代付结果查询TC2002
	 * 		--  用于商户单笔查询代付的交易结果状态
	 *     --  单笔代收交易返回的交易状态未确定时使用
	 */
	public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
		RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
		RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();
		
		try{
			ActSetItem actItem = getBankConfig().getActSetItem(p_req1944.payAct, "");
			if (actItem == null) {
				tmpRetAtsDetail.respCode = "0";
				tmpRetAtsDetail.respInfo = "未找到账号" + p_req1944.recAct + "对应的商户配置信息";
				tmpRetAtsDetail.reqSeqID = p_req1944.askNumber;
				tmpRetAtsDetail.transAmt = p_req1944.payAmount;
				tmpRetAtsDetail.transState = PaymentState.FAIL_Payment;
				tmpRetAtsDetail.payInfoCode = FailCode.E9981;
				
				retAts.writeRetDetail(tmpRetAtsDetail);
				return retAts;
			}
			
			JYTPAY01Header bankHeader = new JYTPAY01Header();
			bankHeader.tran_code = "TC2002";
			bankHeader.tran_flowid = actItem.merchantId + Format.DateTime14Format.format(new Date()) + String.format("%06d", new Random().nextInt(999999));
			
			XmlTextWriter xmlWriter = new XmlTextWriter();
			writeCommonHeader(xmlWriter, bankHeader, actItem);
			
			xmlWriter.writeStartElement("body");
			xmlWriter.writeElementString("ori_tran_flowid", p_req1944.askNumber);// 代付原交易流水号
			xmlWriter.writeEndElement();
			xmlWriter.writeEndDocument();
				
			// 报文明文
			WriteBankLogLn2("金运通单笔代付交易请求报文: \n" + xmlWriter.toXmlString());
			
			// 加密报文并生成签名
			String[] postStr = encryptAndSign(xmlWriter.toXmlString(),actItem);
			
			// http请求数据
			Map<String,String> postParams = new HashMap<String,String>();
			postParams.put("merchant_id", actItem.merchantId);
			postParams.put("xml_enc", postStr[0]);// 加密报文
			postParams.put("key_enc", postStr[1]);// 加密密钥
			postParams.put("sign", postStr[2]);// 签名
			
			// 发送金运通
			String[] tmpStrRet = sendToBank("unifiedPay",postParams);
			
			// 解析金运通返回
			if(tmpStrRet[0].length() == 0) {
				// http返回数据
				WriteBankLogLn2("金运通http返回数据: \n" + tmpStrRet[1]);
				
				String[] respHttpStr = tmpStrRet[1].split("&");
				String hexXmlEnc = respHttpStr[1].split("=")[1].replace("\"", "");// 返回报文密文
				String hexKeyEnc = respHttpStr[2].split("=")[1].replace("\"", "");// 会话密钥密文
				String hexSign = respHttpStr[3].split("=")[1].replace("\"", "");// 签名
				
				// 解密验签
				String[] tmpRespStr = decryptAndVeriSign(hexXmlEnc, hexKeyEnc, hexSign, actItem);
				String respXml = tmpRespStr[0];// 返回报文明文
				String respSign = tmpRespStr[1];// 验签结果
				
				// 验签处理
				if (respSign.equals("1")) {
					// 返回报文
					WriteBankLogStep3(respXml);
					
					// 解析报文
					StringBuilder tmpSbMsg = new StringBuilder();
					XmlTextReader tmpBkReader = loadBankRespXmlReader(respXml, tmpSbMsg);
						
					if(tmpBkReader != null){
						String tmpRespCode = tmpBkReader.getFirstText("/message/head/resp_code");
						String tmpRespInfo = tmpBkReader.getFirstText("/message/head/resp_desc");
						
						if (tmpRespCode.equals("S0000000")) {
							String tranRespCode = tmpBkReader.getFirstText("/message/body/tran_resp_code");
							
							tmpRetAtsDetail.respCode = "0";
							tmpRetAtsDetail.respInfo = tmpRespInfo;
							tmpRetAtsDetail.reqSeqID =  p_req1944.askNumber;
							tmpRetAtsDetail.transAmt = p_req1944.payAmount;
							tmpRetAtsDetail.transState = tranRespCode + "+" + tmpBkReader.getFirstText("/message/body/tran_state");
							tmpRetAtsDetail.payInfoCode = tranRespCode;
						}else {
							tmpRetAtsDetail.respCode = "-1";
							tmpRetAtsDetail.respInfo = tmpRespInfo;
						}
					}else{
						tmpRetAtsDetail.respCode = "-1";
						tmpRetAtsDetail.respInfo = tmpSbMsg.toString();
					}
				} else {
					tmpRetAtsDetail.respCode = "-1";
					tmpRetAtsDetail.respInfo = "验证签名失败!";
				}
			}else{
				tmpRetAtsDetail.respCode = "-1";
				tmpRetAtsDetail.respInfo = tmpStrRet[1];
			}
		}catch (Exception e) {
			tmpRetAtsDetail.respCode = "-1";
			tmpRetAtsDetail.respInfo = e.getMessage();
			e.printStackTrace();
		}
		
		if(tmpRetAtsDetail.respCode.equals("-1") && StringHelper.isNullOrEmpty(tmpRetAtsDetail.reqSeqID)){
			tmpRetAtsDetail.reqSeqID = p_req1944.askNumber;
		}
		
		retAts.writeRetDetail(tmpRetAtsDetail);
		return retAts;
	}

	@Override
	public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
		return null;
	}
}
